import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { UserModule } from './user/user.module';
import * as dotenv from 'dotenv';
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
import { AuthModule } from './auth/auth.module';
import { LogInterceptorInterceptor } from './interceptor/logInterceptor.interceptor';
import { ResponseIntercept } from './interceptor/response.interceptor';
import { GlobalExceptionFilter } from './filters/globalException.filter';
import { HttpExceptionFilter } from './filters/httpException.filter';
import { TypeormFilter } from './filters/typeorm.filter';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigEnum, DbEnum } from './enum/config.enum';
import { LoggerModule } from './logger/logger.module';
import { RedisModule } from '@nestjs-modules/ioredis';
import { IoRedisModule } from './utils/module/redis.module';
import { NotifyModule } from './notify/notify.module';
import { SmsModule } from './utils/module/sms.module';
import { UploadModule } from './upload/upload.module';
const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [
        () => {
          const values = dotenv.config({ path: '.env' });
          return values;
        },
      ],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) =>
        ({
          type: configService.get<string>(DbEnum['DB.TYPE']),
          host: configService.get<string>(DbEnum['DB.HOST']),
          port: configService.get<string>(DbEnum['DB.PORT']),
          username: configService.get<string>(DbEnum['DB.USERNAME']),
          password: configService.get<string>(DbEnum['DB.PASSWORD']),
          database: configService.get<string>(DbEnum['DB.DATABASE']),
          synchronize: false,
          logging:
            process.env.NODE_ENV == 'production'
              ? ['error', 'query', 'schema']
              : true,
          entities: [__dirname + '/**/*.entity{.ts,.js}'],
          poolSize: 10,
          maxQueryExecutionTime: 10000,
          keepConnectionAlive: true,
          connectorPackage: 'mysql2',
          extra: {
            authPlugin: 'sha256_password',
            charset: 'utf8mb4', // 使用utf8mb4字符集支持emoji等
          },
        }) as unknown as TypeOrmModuleOptions,
    }),
    RedisModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => {
        const type = configService.get(ConfigEnum.REDIS_TYPE);
        const host = configService.get(ConfigEnum.REDIS_HOST);
        const port = configService.get(ConfigEnum.REDIS_PORT);
        const password = configService.get(ConfigEnum.REDIS_PASSWORD);
        return {
          type,
          url: host,
          options: {
            port,
            password,
          },
        };
      },
    }),
    LoggerModule,
    UserModule,
    AuthModule,
    IoRedisModule,
    NotifyModule,
    SmsModule,
    UploadModule,
  ],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: LogInterceptorInterceptor,
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: ResponseIntercept,
    },
    {
      provide: APP_FILTER,
      useClass: GlobalExceptionFilter,
    },
    {
      provide: APP_FILTER,
      useClass: HttpExceptionFilter,
    },
    {
      provide: APP_FILTER,
      useClass: TypeormFilter,
    },
  ],
})
export class AppModule {}
